package luke.audio.processor;


import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameFilter;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FFmpegLogCallback; // 添加日志回调导入

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;

public class AudioSpeedChanger {

    /**
     * 处理WAV音频字节数组，实现变速不变调
     * @param audioFile 原始音频文件
     * @param speed 变速比例（0.5-2.0，例如1.2表示1.2倍速）
     * @return 处理后的WAV音频字节数组
     * @throws Exception 处理过程中的异常
     */
    public static byte[] changeSpeedWithoutPitch(File audioFile, double speed) throws Exception {
        // 启用FFmpeg详细日志输出
        FFmpegLogCallback.set();
        byte[] wavBytes = AudioTranscoder.convertFileToWAV(audioFile);
        // 校验变速比例（rubberband滤镜通常支持0.5-2.0范围）
        if (speed <= 0.5 || speed > 2.0) {
            throw new IllegalArgumentException("变速比例需在0.5-2.0之间");
        }

        // 1. 从字节数组读取WAV音频
        try (InputStream inputStream = new ByteArrayInputStream(wavBytes);
             FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputStream)) {
            grabber.start();

            // 2. 配置变速滤镜（使用atempo作为更稳定的替代方案）
            // 如果speed超出0.5-2.0范围，需要分段处理
            String filterSpec = createTempoFilter(speed);
            FFmpegFrameFilter filter = new FFmpegFrameFilter(filterSpec, grabber.getAudioChannels());
            filter.setSampleRate(grabber.getSampleRate());
            filter.start();

            // 3. 将处理后的音频写入字节数组（输出为WAV格式）
            try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                 FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputStream, grabber.getAudioChannels())) {
                // 配置输出参数（与输入保持一致，确保WAV格式正确）
                recorder.setFormat("wav");
                recorder.setSampleRate(grabber.getSampleRate());
                recorder.setSampleFormat(avutil.AV_SAMPLE_FMT_S16); // WAV常用16位采样格式
                recorder.setAudioBitrate(grabber.getAudioBitrate());
                recorder.start();

                // 4. 处理音频帧：读取->过滤->写入
                Frame frame;
                while ((frame = grabber.grabSamples()) != null) {
                    filter.push(frame);
                    Frame filteredFrame;
                    while ((filteredFrame = filter.pull()) != null) {
                        recorder.record(filteredFrame);
                    }
                }

                // 释放资源
                filter.stop();
                recorder.stop();
                grabber.stop();

                return outputStream.toByteArray();
            }
        }
    }
    
    /**
     * 创建 tempo 滤镜字符串，支持超出0.5-2.0范围的速度调整
     * @param speed 速度比例
     * @return 滤镜字符串
     */
    private static String createTempoFilter(double speed) {
        // 使用 atempo 滤镜，支持0.5-2.0范围
        // 如果超出范围，需要分段处理
        if (speed < 0.5) {
            // 低于0.5时，分段处理
            int segments = (int) Math.ceil(Math.log(0.5 / speed) / Math.log(2));
            double segmentSpeed = Math.pow(0.5, 1.0 / segments);
            StringBuilder filterBuilder = new StringBuilder();
            for (int i = 0; i < segments; i++) {
                if (i > 0) filterBuilder.append(",");
                filterBuilder.append(String.format("atempo=%.4f", segmentSpeed));
            }
            return filterBuilder.toString();
        } else if (speed > 2.0) {
            // 高于2.0时，分段处理
            int segments = (int) Math.ceil(Math.log(speed / 2.0) / Math.log(2));
            double segmentSpeed = Math.pow(2.0, 1.0 / segments);
            StringBuilder filterBuilder = new StringBuilder();
            for (int i = 0; i < segments; i++) {
                if (i > 0) filterBuilder.append(",");
                filterBuilder.append(String.format("atempo=%.4f", segmentSpeed));
            }
            // 添加最终调整
            double finalSpeed = speed / Math.pow(2.0, segments);
            if (finalSpeed > 0.5 && finalSpeed <= 2.0) {
                filterBuilder.append(String.format(",atempo=%.4f", finalSpeed));
            }
            return filterBuilder.toString();
        } else {
            // 在0.5-2.0范围内，直接使用
            return String.format("atempo=%.4f", speed);
        }
    }
}